/*
 * Copyright 2002-2006 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.cpbi.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.osgi.framework.Constants;

/**
 * A simple wrapper for {@link Manifest} with a getter and setter for each OSGi Bundle Manifest Header, enabling easy
 * configuration and use of a Bundle Manifest as a JavaBean.
 * 
 * @author Jeremy Wales
 */
public final class BundleManifest {
	private Manifest wrappedManifest;

	/**
	 * Constructs a new BundleManifest backed by a new {@link Manifest}. Sets
	 * <p>
	 * Manifest-Version: 1.0
	 * </p>
	 * <p>
	 * Bundle-ManifestVersion: 2
	 * </p>
	 * as convenient defaults.
	 */
	public BundleManifest() {
		wrappedManifest = new Manifest();
		set(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
		setManifestVersion("2");
	}

	/**
	 * Constructs a new BundleManifestWrapper backed by the given {@link Manifest}.
	 * 
	 * @param manifest the manifest which will be wrapped by the newly constructed BundleManifestWrapper.
	 */
	public BundleManifest(Manifest manifest) {
		if (manifest == null) throw new IllegalArgumentException("The given Manifest was null but must not be.");
		wrappedManifest = manifest;
	}

	public String getManifestVersion() {
		return get(Constants.BUNDLE_MANIFESTVERSION);
	}

	public void setManifestVersion(String value) {
		set(Constants.BUNDLE_MANIFESTVERSION, value);
	}

	public String getSymbolicName() {
		return get(Constants.BUNDLE_SYMBOLICNAME);
	}

	public void setSymbolicName(String value) {
		set(Constants.BUNDLE_SYMBOLICNAME, value);
	}

	public String getVersion() {
		return get(Constants.BUNDLE_VERSION);
	}

	public void setVersion(String value) {
		set(Constants.BUNDLE_VERSION, value);
	}

	public String getName() {
		return get(Constants.BUNDLE_NAME);
	}

	public void setName(String value) {
		set(Constants.BUNDLE_NAME, value);
	}

	public String getFragmentHost() {
		return get(Constants.FRAGMENT_HOST);
	}

	public void setFragmentHost(String value) {
		set(Constants.FRAGMENT_HOST, value);
	}

	public String getClassPath() {
		return get(Constants.BUNDLE_CLASSPATH);
	}

	public void setClassPath(String value) {
		set(Constants.BUNDLE_CLASSPATH, value);
	}

	public String getUpdateLocation() {
		return get(Constants.BUNDLE_UPDATELOCATION);
	}

	public void setUpdateLocation(String value) {
		set(Constants.BUNDLE_UPDATELOCATION, value);
	}

	public String getActivator() {
		return get(Constants.BUNDLE_ACTIVATOR);
	}

	public void setActivator(String value) {
		set(Constants.BUNDLE_ACTIVATOR, value);
	}

	public String getExportPackage() {
		return get(Constants.EXPORT_PACKAGE);
	}

	public void setExportPackage(String value) {
		set(Constants.EXPORT_PACKAGE, value);
	}

	public String getImportPackage() {
		return get(Constants.IMPORT_PACKAGE);
	}

	public void setImportPackage(String value) {
		set(Constants.IMPORT_PACKAGE, value);
	}

	public String getDynamicImportPackage() {
		return get(Constants.DYNAMICIMPORT_PACKAGE);
	}

	public void setDynamicImportPackage(String value) {
		set(Constants.DYNAMICIMPORT_PACKAGE, value);
	}

	public String getExportService() {
		return get(Constants.EXPORT_SERVICE);
	}

	public void setExportService(String value) {
		set(Constants.EXPORT_SERVICE, value);
	}

	public String getImportService() {
		return get(Constants.IMPORT_SERVICE);
	}

	public void setImportService(String value) {
		set(Constants.IMPORT_SERVICE, value);
	}

	public String getRequireBundle() {
		return get(Constants.REQUIRE_BUNDLE);
	}

	public void setRequireBundle(String value) {
		set(Constants.REQUIRE_BUNDLE, value);
	}

	public String getRequiredExecutionEnvironment() {
		return get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
	}

	public void setRequiredExecutionEnvironment(String value) {
		set(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT, value);
	}

	public String getNativeCode() {
		return get(Constants.BUNDLE_NATIVECODE);
	}

	public void setNativeCode(String value) {
		set(Constants.BUNDLE_NATIVECODE, value);
	}

	public String getCategory() {
		return get(Constants.BUNDLE_CATEGORY);
	}

	public void setCategory(String value) {
		set(Constants.BUNDLE_CATEGORY, value);
	}

	public String getDescription() {
		return get(Constants.BUNDLE_DESCRIPTION);
	}

	public void setDescription(String value) {
		set(Constants.BUNDLE_DESCRIPTION, value);
	}

	public String getCopyright() {
		return get(Constants.BUNDLE_COPYRIGHT);
	}

	public void setCopyright(String value) {
		set(Constants.BUNDLE_COPYRIGHT, value);
	}

	public String getContactAddress() {
		return get(Constants.BUNDLE_CONTACTADDRESS);
	}

	public void setContactAddress(String value) {
		set(Constants.BUNDLE_CONTACTADDRESS, value);
	}

	public String getDocUrl() {
		return get(Constants.BUNDLE_DOCURL);
	}

	public void setDocUrl(String value) {
		set(Constants.BUNDLE_DOCURL, value);
	}

	public String getVendor() {
		return get(Constants.BUNDLE_VENDOR);
	}

	public void setVendor(String value) {
		set(Constants.BUNDLE_VENDOR, value);
	}

	public String getLocalization() {
		return get(Constants.BUNDLE_LOCALIZATION);
	}

	public void setLocalization(String value) {
		set(Constants.BUNDLE_LOCALIZATION, value);
	}

	private String set(String header, String value) {
		return wrappedManifest.getMainAttributes().putValue(header, value);
	}

	private String get(String header) {
		return wrappedManifest.getMainAttributes().getValue(header);
	}

	/**
	 * For retrieving the wrapped {@link Manifest}.
	 * 
	 * @return the {@link Manifest} configured by this BundleManifestWrapper.
	 */
	public Manifest getManifest() {
		return wrappedManifest;
	}

	/**
	 * {@inheritDoc}
	 */
	public String toString() {
		// TODO test drive BundleManifest toString
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		try {
			wrappedManifest.write(outputStream);
			return new String(outputStream.toByteArray());
		} catch (IOException e) {
			throw new CpbiException("Cannot write wrapped manifest.", e);
		}
	}
}
